package cn.edu.zut.qixiang.mock;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;

/**
 * 温度数据采集表数据生成器
 * 为温度数据采集站生成模拟数据（每隔10分钟采集一次）
 * @author 86178
 */
public class TemperatureDataGenerator {

    // 数据库配置
    private static final String URL = "jdbc:mysql://localhost:3306/qixiang_base?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
    private static final String USER = "root";
    private static final String PASSWORD = "520521fcf..@1234";

    // 数据生成参数
    private static final int BATCH_SIZE = 100;
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        generateTemperatureData();
    }

    /**
     * 生成温度数据（每隔10分钟采集一次）
     */
    public static void generateTemperatureData() {
        String selectStationsSql = "SELECT station_id FROM collection_stations WHERE station_type = '温度数据采集站' ORDER BY station_id";
        String insertDataSql = "INSERT INTO temperature_data (collection_station_id, temperature, collection_time) VALUES (?, ?, ?)";

        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             PreparedStatement selectStmt = conn.prepareStatement(selectStationsSql);
             PreparedStatement insertStmt = conn.prepareStatement(insertDataSql)) {

            conn.setAutoCommit(false);
            Random random = new Random();

            // 获取所有温度数据采集站
            ResultSet stationRs = selectStmt.executeQuery();

            int batchCount = 0;
            int totalRecords = 0;
            int stationCount = 0;

            // 生成2025年5月1日到9月1日的数据，每10分钟一次
            LocalDateTime startTime = LocalDateTime.of(2025, 5, 1, 0, 0, 0);
            LocalDateTime endTime = LocalDateTime.of(2025, 9, 1, 23, 50, 0);

            System.out.println("开始生成温度数据...");
            System.out.println("时间范围: " + startTime.format(DATE_FORMATTER) + " 到 " + endTime.format(DATE_FORMATTER));
            System.out.println("采集频率: 每10分钟一次");

            // 遍历每个温度采集站
            while (stationRs.next()) {
                int stationId = stationRs.getInt("station_id");
                stationCount++;
                System.out.println("为采集站 " + stationId + " 生成数据...");

                LocalDateTime currentTime = startTime;

                // 为每个时间点生成数据（每10分钟一次）
                while (!currentTime.isAfter(endTime)) {
                    // 生成温度数据
                    double temperature = generateTemperature(currentTime, random, stationId);

                    // 设置插入参数
                    insertStmt.setInt(1, stationId);
                    insertStmt.setDouble(2, temperature);
                    insertStmt.setString(3, currentTime.format(DATE_FORMATTER));

                    insertStmt.addBatch();
                    batchCount++;
                    totalRecords++;

                    // 批量提交
                    if (batchCount % BATCH_SIZE == 0) {
                        insertStmt.executeBatch();
                        conn.commit();
                        System.out.println("已提交 " + batchCount + " 条记录，总计 " + totalRecords + " 条");
                    }

                    // 时间增加10分钟
                    currentTime = currentTime.plusMinutes(10);
                }
            }

            // 提交剩余数据
            if (batchCount % BATCH_SIZE != 0) {
                insertStmt.executeBatch();
                conn.commit();
            }

            System.out.println("温度数据生成完成！");
            System.out.println("共为 " + stationCount + " 个采集站生成 " + totalRecords + " 条记录");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成温度数据
     * 模拟真实的温度变化模式：日变化、季节变化、天气影响
     */
    private static double generateTemperature(LocalDateTime time, Random random, int stationId) {
        int month = time.getMonthValue();
        int hour = time.getHour();
        int minute = time.getMinute();

        // 基准温度（郑州地区5-9月温度范围）
        double baseTemperature = getMonthlyBaseTemperature(month);

        // 日变化（温度在一天中的变化）
        double diurnalVariation = calculateDiurnalVariation(hour, minute, month);

        // 天气影响（晴天、阴天、雨天的温度差异）
        double weatherEffect = calculateWeatherEffect(time, random);

        // 站点差异（城市热岛效应等）
        double stationVariation = calculateStationVariation(stationId, time);

        // 随机波动
        double randomFluctuation = (random.nextDouble() - 0.5) * 2.0;

        // 计算最终温度
        double temperature = baseTemperature + diurnalVariation + weatherEffect + stationVariation + randomFluctuation;

        return Math.round(temperature * 10) / 10.0;
    }

    /**
     * 获取各月基准温度（郑州地区5-9月）
     */
    private static double getMonthlyBaseTemperature(int month) {
        switch (month) {
            case 5: // 5月：春末，温度适中
                return 22.0;
            case 6: // 6月：初夏，温度升高
                return 26.0;
            case 7: // 7月：盛夏，最热
                return 28.5;
            case 8: // 8月：盛夏，温度稍降
                return 27.5;
            case 9: // 9月：初秋，温度下降
                return 23.0;
            default:
                return 25.0;
        }
    }

    /**
     * 计算温度的日变化
     * 最低温度在日出前（5-6时），最高温度在午后（14-15时）
     */
    private static double calculateDiurnalVariation(int hour, int minute, int month) {
        double timeOfDay = hour + minute / 60.0;

        // 根据季节调整日变化幅度（夏季日较差大，春秋季较小）
        double amplitude = getDiurnalAmplitude(month);

        // 最低温度时间（日出前）
        double minTempHour = 5.5;
        // 最高温度时间（午后）
        double maxTempHour = 14.5;

        // 计算相对于最低温度时间的小时差
        double hourDiff = timeOfDay - minTempHour;
        if (hourDiff < 0) {
            hourDiff += 24;
        }

        // 使用分段函数模拟温度日变化
        double variation;
        if (hourDiff <= (maxTempHour - minTempHour)) {
            // 升温阶段：从最低点到最高点
            double progress = hourDiff / (maxTempHour - minTempHour);
            variation = amplitude * progress;
        } else {
            // 降温阶段：从最高点到次日最低点
            double progress = (hourDiff - (maxTempHour - minTempHour)) / (24 - (maxTempHour - minTempHour));
            variation = amplitude * (1 - progress);
        }

        return variation;
    }

    /**
     * 获取日较差（日最高温与最低温的差值）
     */
    private static double getDiurnalAmplitude(int month) {
        switch (month) {
            case 5: // 5月：日较差较大
                return 10.0;
            case 6: // 6月：日较差大
                return 12.0;
            case 7: // 7月：日较差最大
                return 13.0;
            case 8: // 8月：日较差大
                return 11.0;
            case 9: // 9月：日较差适中
                return 9.0;
            default:
                return 10.0;
        }
    }

    /**
     * 计算天气对温度的影响
     */
    private static double calculateWeatherEffect(LocalDateTime time, Random random) {
        // 使用日期作为种子，使同一日期的天气一致
        long daySeed = time.toLocalDate().toEpochDay();
        Random dayRandom = new Random(daySeed);

        // 模拟天气类型：0-晴天, 1-多云, 2-阴天, 3-雨天
        int weatherType = dayRandom.nextInt(4);

        switch (weatherType) {
            case 0: // 晴天：白天温度较高，夜间辐射降温明显
                return (time.getHour() >= 6 && time.getHour() <= 18) ? 2.0 : -3.0;
            case 1: // 多云：温度适中
                return 0.0;
            case 2: // 阴天：白天温度较低，夜间保温
                return (time.getHour() >= 6 && time.getHour() <= 18) ? -2.0 : 1.0;
            case 3: // 雨天：全天温度较低
                return -4.0;
            default:
                return 0.0;
        }
    }

    /**
     * 计算站点差异（城市热岛效应、海拔差异等）
     */
    private static double calculateStationVariation(int stationId, LocalDateTime time) {
        // 模拟城市热岛效应：市中心站点温度较高
        boolean isUrbanCenter = (stationId % 3 == 0); // 假设每3个站点中有一个是市中心站点

        if (isUrbanCenter) {
            // 市中心夜间热岛效应更明显
            return (time.getHour() >= 18 || time.getHour() <= 6) ? 1.5 : 0.8;
        }

        // 郊区站点温度稍低
        return -0.5;
    }
}